﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BoAddonBiz_FreightForwarder.BusinessBase
{
    class SerialNumber
    {
        #region Initialization
        private static object mylock = new object();
        private static SerialNumber Instance;
        private SerialNumber()
        { }
        public static SerialNumber GetInstance()
        {
            if (Instance == null)
                lock (mylock)
                {
                    if (Instance == null)
                        Instance = new SerialNumber();
                }
            return Instance;
        }
        #endregion
        public bool ExistsRecoveryNumber { get; set; }
        //private bool IsInvalidNum;//是否作废流水号

        //private string mySerialNumber { get; set; }  /*deleted by WangPeng 2012-6-11*/
        public string RecoveryNumber { get; set; }
        public string RecoveryTransportType { get; set; }
        private string FirstInvalidNum { get; set; }//第一个作废号

        public void GetSerialNumberByProc(SAPbouiCOM.Form oForm)
        {
            string mySerialNumber = string.Empty;
            SAPbouiCOM.DBDataSource dbds;
            SAPbobsCOM.Recordset oRst;
            string TransportType = string.Empty;
            string SQL = string.Empty;
            oRst = SAPBoAddon.B1Addon.B1Addon.SBOCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.BoRecordset);
            dbds = oForm.DataSources.DBDataSources.Item(oForm.Items.Item(oForm.DataBrowser.BrowseBy).Specific.DataBind.TableName);
            //空运业务单
            if (oForm.TypeEx == B1FormTypes.ado_AVA_FF_BusinessOperation 
                || oForm.TypeEx == B1FormTypes.ado_AVA_SE_BusinessOperation 
                || oForm.TypeEx == B1FormTypes.ado_AVA_LN_BusinessOperation
                || oForm.TypeEx == B1FormTypes.ado_AVA_OR_BusinessOperation)
            {
                //获取当前单据类型
                TransportType = dbds.GetValue("U_TransportType", dbds.Offset).Trim();
            }
            string BusinessObjectCode = oForm.BusinessObject.Type;
            SQL = string.Format("EXEC AVA_AL_GetSerialNumber N'{0}',N'{1}'  ", BusinessObjectCode, TransportType);
            oRst.DoQuery(SQL);
            if (oRst.RecordCount > 0)
            {
                mySerialNumber = oRst.Fields.Item("SerNum").Value;

                dbds.SetValue("U_SerialNum", dbds.Offset, mySerialNumber);
                //Log.GetInstance().Write("获取流水号：" + mySerialNumber + "  单据：" + oForm.TypeEx);/*去掉写日志 12-7-23 by WangPeng*/
            }
        }

        /// <summary>
        /// 查找流水号的运输类型
        /// </summary>
        /// <author>WangPeng</author>
        private string GetTransType(string CurrentNum)
        {
            IEnumerable<char> char_num = from cItem in CurrentNum
                                         where Char.IsNumber(cItem)
                                         select cItem;
            string TransType = CurrentNum.Substring(0, CurrentNum.IndexOf(char_num.ElementAt(0)));
            return TransType;
        }
        /// <summary>
        /// 数据加载记录流水号(检查是否回收是使用)
        /// </summary>
        /// <author>WangPeng</author>
        public void RecordSerialNumInUds(SAPbouiCOM.Form oForm)
        {
            SAPbouiCOM.DBDataSource dbds = oForm.DataSources.DBDataSources.Item(oForm.Items.Item(oForm.DataBrowser.BrowseBy).Specific.DataBind.TableName);
            if (string.IsNullOrEmpty(oForm.DataSources.UserDataSources.Item("LSerNum").ValueEx.Trim()))
                oForm.DataSources.UserDataSources.Item("LSerNum").ValueEx = dbds.GetValue("U_SerialNum", dbds.Offset).Trim();
        }
        #region 流水码处理
        /// <summary>
        /// 流水码处理
        /// </summary>
        /// <param name="oForm"></param>
        public string CreateSerialNumber(String FormType, string SerialNumber = "")
        {
            SAPbobsCOM.Recordset ors;
            string CurrentKey = string.Empty;//当前字符串
            string Code = string.Empty;
            int Length = 0;
            IList<SerialNumberRule> oNumberRuleList = new List<SerialNumberRule>();
            string DateFormatString = string.Empty; //日期格式
            string ResetFormetString = string.Empty;//重置参考标志的格式
            NumberRuleResetReference Reset = default(NumberRuleResetReference);//重置参考的标志

            int DateFormatStart = 0;/*日期格式开始索引*/
            int DateFormatEnd = 0;//日期格式结束索引
            if (!SAPBoAddon.B1Addon.B1Addon.SBOCompany.InTransaction)
            {
                SAPBoAddon.B1Addon.B1Addon.SBOCompany.StartTransaction();
            }

            try
            {
                ors = SAPBoAddon.B1Addon.B1Addon.SBOCompany.GetBusinessObject(SAPbobsCOM.BoObjectTypes.BoRecordset);
                #region 获取编码规则
                ors.DoQuery("SELECT Code,U_IsAutoKey,U_Length,U_CurrentKey FROM [@AVA_FF_ONNM] With(UPDLOCK) Where U_ObjectCode = '" + FormType + "'");
                if (ors.RecordCount <= 0) return "";
                if (ors.Fields.Item("U_IsAutoKey").Value == "N")
                {
                    return "";
                }
                else
                {
                    //判断当前字符串是否是由单据的类型控制的。
                    //如果是单据类型控制则需要传一个字段串
                    CurrentKey = ors.Fields.Item("U_CurrentKey").Value;
                    if (!string.IsNullOrEmpty(SerialNumber))
                        CurrentKey = SerialNumber;
                    Code = ors.Fields.Item("Code").Value;
                    Length = ors.Fields.Item("U_Length").Value;
                    #region
                    ors.DoQuery("SELECT Lineid,U_StartsWith,U_EndsWith,U_CharType,U_AlterType,U_Reset,U_Chars FROM [@AVA_FF_NNM1] With(UPDLOCK) Where Code = '" + Code + "'");
                    if (ors.RecordCount > 0)
                    {
                        for (int i = 0; i < ors.RecordCount; i++)
                        {
                            SerialNumberRule NumberRule = new SerialNumberRule();
                            NumberRule.StartsWith = ors.Fields.Item("U_StartsWith").Value;
                            NumberRule.EndsWith = ors.Fields.Item("U_EndsWith").Value;
                            string CharType = ors.Fields.Item("U_CharType").Value;
                            switch (CharType)
                            {
                                case "F":
                                    NumberRule.CharType = NumberRuleCharType.Fixed;
                                    break;
                                case "C":
                                    NumberRule.CharType = NumberRuleCharType.Alterable;
                                    break;
                                case "S":
                                    NumberRule.CharType = NumberRuleCharType.Serial;
                                    break;
                            }
                            string AlterType = ors.Fields.Item("U_AlterType").Value;
                            switch (AlterType)
                            {
                                case "I":
                                    NumberRule.AlterType = NumberRuleAlterable.Int;
                                    string Value = ors.Fields.Item("U_Reset").Value;
                                    switch (Value)
                                    {
                                        case "Y":
                                            NumberRule.Reset = NumberRuleResetReference.Year;
                                            Reset = NumberRuleResetReference.Year;
                                            ResetFormetString = ors.Fields.Item("U_Chars").Value;
                                            break;
                                        case "M":
                                            NumberRule.Reset = NumberRuleResetReference.Month;
                                            Reset = NumberRuleResetReference.Month;
                                            ResetFormetString = ors.Fields.Item("U_Chars").Value;
                                            break;
                                        case "D":
                                            NumberRule.Reset = NumberRuleResetReference.Day;
                                            Reset = NumberRuleResetReference.Day;
                                            ResetFormetString = ors.Fields.Item("U_Chars").Value;
                                            break;
                                    }
                                    break;
                                case "D":
                                    NumberRule.AlterType = NumberRuleAlterable.Datetime;
                                    DateFormatString = ors.Fields.Item("U_Chars").Value;
                                    DateFormatStart = NumberRule.StartsWith;
                                    DateFormatEnd = NumberRule.EndsWith;
                                    break;
                            };

                            NumberRule.Chars = ors.Fields.Item("U_Chars").Value;
                            oNumberRuleList.Add(NumberRule);
                            ors.MoveNext();
                        }
                    }
                    #endregion
                }
                #endregion
                #region 拼接字符串
                //拼字符串
                if (oNumberRuleList.Count <= 0)
                {
                    CurrentKey = (decimal.Parse((string.IsNullOrEmpty(CurrentKey) ? "0" : CurrentKey)) + 1).ToString("".PadLeft(Length, '0'));
                }
                else
                {
                    string joinstring = string.Empty;
                    foreach (SerialNumberRule oNumberRule in oNumberRuleList)
                    {
                        switch (oNumberRule.CharType)
                        {
                            #region Fixed
                            case NumberRuleCharType.Fixed://固定的字符
                                oNumberRule.AutoKey += oNumberRule.Chars;
                                break;
                            #endregion
                            #region 有规则变化的字符
                            case NumberRuleCharType.Alterable://有规则变化的字符
                                if (oNumberRule.AlterType == NumberRuleAlterable.Datetime)
                                {
                                    oNumberRule.AutoKey += DateTime.Now.ToString(oNumberRule.Chars);
                                }
                                break;
                            #endregion
                            #region 流水码
                            case NumberRuleCharType.Serial://流水号
                                if (oNumberRule.AlterType == NumberRuleAlterable.Int)
                                {
                                    string AlterString = string.Empty;
                                    #region 当前字符为0
                                    if (string.IsNullOrEmpty(CurrentKey))
                                    {
                                        AlterString = "0";
                                    }
                                    else
                                    {
                                        System.Globalization.CultureInfo provider = System.Globalization.CultureInfo.InvariantCulture;
                                        string StringDate = CurrentKey.Substring(DateFormatStart - 1, DateFormatEnd - DateFormatStart + 1);
                                        DateTime dt = DateTime.ParseExact(StringDate, DateFormatString, provider);

                                        switch (Reset)
                                        {
                                            case NumberRuleResetReference.Year:
                                                if (dt.Year != DateTime.Now.Year)
                                                {
                                                    AlterString = "0";
                                                }
                                                else
                                                {
                                                    AlterString = CurrentKey.Substring(oNumberRule.StartsWith - 1, oNumberRule.EndsWith - oNumberRule.StartsWith + 1);
                                                }
                                                break;
                                            case NumberRuleResetReference.Month:
                                                if (dt.Month != DateTime.Now.Month)
                                                {
                                                    AlterString = "0";
                                                }
                                                else
                                                {
                                                    AlterString = CurrentKey.Substring(oNumberRule.StartsWith - 1, oNumberRule.EndsWith - oNumberRule.StartsWith + 1);
                                                }
                                                break;
                                            case NumberRuleResetReference.Day:
                                                if (dt.Day != DateTime.Now.Day)
                                                {
                                                    AlterString = "0";
                                                }
                                                else
                                                {
                                                    AlterString = CurrentKey.Substring(oNumberRule.StartsWith - 1, oNumberRule.EndsWith - oNumberRule.StartsWith + 1);
                                                }
                                                break;
                                        }
                                    }
                                    #endregion
                                    oNumberRule.AutoKey += (decimal.Parse(AlterString) + 1).ToString("".PadLeft(oNumberRule.EndsWith - oNumberRule.StartsWith + 1, '0'));
                                }
                                break;
                            #endregion
                        }
                        joinstring += oNumberRule.AutoKey;
                    }
                    CurrentKey = joinstring;
                }
                #endregion
                return CurrentKey;
            }
            catch (Exception ex)
            {
                if (SAPBoAddon.B1Addon.B1Addon.SBOCompany.InTransaction)
                {
                    SAPBoAddon.B1Addon.B1Addon.SBOCompany.EndTransaction(SAPbobsCOM.BoWfTransOpt.wf_RollBack);
                }
                throw ex;
            }
            finally
            {
                if (SAPBoAddon.B1Addon.B1Addon.SBOCompany.InTransaction)
                {
                    SAPBoAddon.B1Addon.B1Addon.SBOCompany.EndTransaction(SAPbobsCOM.BoWfTransOpt.wf_Commit);
                }
            }
        }
        #endregion
    }

    internal enum SerialNum_State
    {
        /// <summary>
        /// 作废
        /// </summary>
        ss_Invalid = 0,
        /// <summary>
        /// 重新使用
        /// </summary>
        ss_ReUse = 1
    }
    #region 流水码的编码规则
    /// <summary>
    /// 编码规则
    /// </summary>
    internal class SerialNumberRule
    {
        private int _StartsWith;
        /// <summary>
        /// 开始位置
        /// </summary>
        public int StartsWith
        {
            get { return _StartsWith; }
            set { _StartsWith = value; }
        }
        private int _EndsWith;
        /// <summary>
        /// 结束位置
        /// </summary>
        public int EndsWith
        {
            get { return _EndsWith; }
            set { _EndsWith = value; }
        }
        private NumberRuleCharType _CharType;
        /// <summary>
        /// 字段串类型
        /// </summary>
        public NumberRuleCharType CharType
        {
            get { return _CharType; }
            set { _CharType = value; }
        }
        private NumberRuleAlterable _AlterType;
        /// <summary>
        /// 可变类型
        /// </summary>
        public NumberRuleAlterable AlterType
        {
            get { return _AlterType; }
            set { _AlterType = value; }
        }
        private NumberRuleResetReference _Reset;
        /// <summary>
        /// 重置流水码的参考标准
        /// </summary>
        internal NumberRuleResetReference Reset
        {
            get { return _Reset; }
            set { _Reset = value; }
        }
        private string _Chars;
        /// <summary>
        /// 字符串
        /// </summary>
        public string Chars
        {
            get { return _Chars; }
            set { _Chars = value; }
        }
        private string _AutoKey;
        /// <summary>
        /// 最终的字符串
        /// </summary>
        public string AutoKey
        {
            get { return _AutoKey; }
            set { _AutoKey = value; }
        }
    }
    #endregion
    #region enum
    internal enum NumberRuleCharType
    {
        Fixed = 1,
        Alterable,
        Serial
    }
    internal enum NumberRuleAlterable
    {
        Int = 1,
        Datetime = 2
    }
    internal enum NumberRuleResetReference
    {
        Year,
        Month,
        Day
    }
    #endregion
}
